package com.openlogic.common.logic.run;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.text.StringEscapeUtils;
import org.noear.solon.annotation.Component;
import org.noear.solon.core.event.AppBeanLoadEndEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.googlecode.aviator.AviatorEvaluator;
import com.googlecode.aviator.Expression;
import com.openlogic.common.core.utils.DateUtils;
import com.openlogic.common.logic.constants.RuleConstants;
import com.openlogic.common.logic.node.enums.NodeExecEnums;
import com.openlogic.common.logic.node.enums.OpTypeEnums;
import com.openlogic.common.logic.node.factory.NodeExecFactory;
import com.openlogic.common.logic.utils.NumericRegxUtils;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

/**
* @ClassName: ExecSwitchNodeHandler
* @Description: 分支节点运行执行器
* @author weiyongpeng
* @date 2024年7月17日 上午9:12:36
 */
@Component
public class ExecSwitchNodeHandler extends ExecRuleHandler{
	
	private static final Logger logger = LoggerFactory.getLogger(ExecSwitchNodeHandler.class);

	@Override
	public JSONObject typeRun(JSONArray resultArray1,JSONArray nodeArray,JSONArray lineArray,JSONObject inputjson,JSONArray areaArray,String areaFirst,String ruleId,StringBuffer reason,Map<String,Object> map) {
		JSONObject reJson = new JSONObject();
		logger.info("SwitchNode Begin Run Starting...");
		// 分支节点解析后的数据
		logger.info("typeRun=====" +  resultArray1.toString());
		reJson = recRunForNode(resultArray1,nodeArray,lineArray,inputjson,areaArray,areaFirst,ruleId,reason,map);	
		return reJson;
	}

	/**
	* 描述：迭代节点执行
	* @Title: recRunForDefault
	* @param resultArray1
	* @param nodeArray
	* @param lineArray
	* @param inputjson
	* @param areaArray
	* @param areaFirst
	* @param ruleId
	* @param reason
	* @param map
	* @return
	* @author weiyongpeng
	* @date  2024年7月17日 上午10:29:23
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	@Override
	protected JSONObject recRunForNode(JSONArray resultArray1, JSONArray nodeArray, JSONArray lineArray,
			JSONObject inputjson, JSONArray areaArray, String areaFirst, String ruleId, StringBuffer reason,
			Map<String, Object> map) {
		Map<Object,Object> inParam = new HashMap<>();
		for (Object ijo : inputjson.entrySet()){
	    	if(!((Map.Entry)ijo).getKey().toString().equals("everyNodeList") && !((Map.Entry)ijo).getKey().toString().equals("areaInfo") ) {
	    		inParam.put(((Map.Entry)ijo).getKey().toString().replaceAll("\"", ""), ((Map.Entry)ijo).getValue().toString().replaceAll("\"", ""));
	    	}
	    }
		// 开始执行时间
		Date startDate = DateUtils.getNowDate();
		String startExecuateTime = DateUtils.formatDate(startDate, DateUtils.YYYY_MM_DD_HH_MM_SS);
		boolean result=true;
		JSONObject reJson = new JSONObject();
		JSONArray lineArray1 = new JSONArray();
		JSONArray lineArraylist = new JSONArray();
		String valString = ((JSONObject)resultArray1.get(3)).get("value").toString();
		valString = StringEscapeUtils.unescapeXml(valString);
		
		if(map.isEmpty()) {
			map = ((Map<String, Object>)Optional.ofNullable(JSONObject.fromObject(resultArray1.get(8))).orElse(new JSONObject()));
		}

		//遍历替换变量
		inputjson = sortJson(inputjson);
		Map<String, Object> env = inputjson;
		Iterator<String> it1 = inputjson.keys();
		String valStringOld = valString;
		
		// 判断是否存在sql参数
		if (valString.contains("@")) { // sql参数
			// 假如SQL参数是前缀带@ @MIN_VALUE > MAX_VALUE
			// 遍历替换if中的变量
			while (it1.hasNext()) {
				// 获得key
				String key = it1.next();
				if (valString.contains("@" + key + "@")) {
					// 根据参数名称查询SQL参数
					try {
						selectRuleSqlParamRes(inputjson, key, env);
					} catch (SQLException e) {
						e.printStackTrace();
					}
					valString = valString.replaceAll("\\@" + key + "\\@", key);
					valStringOld = valStringOld.replaceAll("\\@" + key + "\\@", map.get(key).toString());
				} else if (extractStrings(valString).stream().filter(s -> s.split("\\.").length >= 2)
						.collect(Collectors.toList()).size() > 0) {
					// @sqlVar2.NAME@.contains('10')
					List<String> sqlVarList = extractStrings(valString).stream().filter(s -> s.split("\\.").length >= 2)
							.collect(Collectors.toList());
					for (String sqlVar : sqlVarList) {
						String[] sqlSplit = sqlVar.split("\\.");
						// 取出需要对比的字段
						String compareVar = sqlSplit[1];
						List<Object> columnValueList = new ArrayList<>();
						if (sqlSplit[0].equals(key)) {
							List<Map<String, Object>> listObjectFir = (List<Map<String, Object>>) com.alibaba.fastjson.JSONArray
									.parse((String) sqlCache.get(key));
							if (CollectionUtils.isEmpty(listObjectFir)) {
								try {
									listObjectFir = selectRuleSqlParamRes(inputjson, key, env);
								} catch (SQLException e) {
									e.printStackTrace();
								}
							}
							columnValueList = listObjectFir.stream()
									.filter(mapF -> Optional.ofNullable(mapF.get(compareVar)).isPresent()).map(mapV -> {
										Object value = mapV.get(compareVar);
										return value;
									}).collect(Collectors.toList());
							env.put(sqlVar.replaceAll("\\.", ""), columnValueList);
							valString = valString.replaceAll("\\@" + sqlVar + "\\@", sqlVar.replaceAll("\\.", ""));
							valStringOld = valStringOld.replaceAll("\\@" + sqlVar + "\\@", map.get(key).toString());
						} else {
							break;
						}
					}
				} else {
					valString = valString.replaceAll("'" + key + "'",
							NumericRegxUtils.isNumber(inputjson.getString(key)) ? inputjson.getString(key)
									: "'" + inputjson.getString(key) + "'");
					valStringOld = valStringOld.replaceAll("'" + key + "'",
							NumericRegxUtils.isNumber(inputjson.getString(key))
									? map.get(key) == null ? inputjson.getString(key) : map.get(key).toString()
									: "'" + inputjson.getString(key) + "'");
				}
			}
		} 
		valStringOld = valStringOld.replaceAll("&&", "并且").replaceAll("\\|\\|", "或者");

		//找下级节点    
		lineArraylist =(JSONArray) resultArray1.get(7);
		//执行if判断
		for(int h=0,listlength=lineArraylist.size();h<listlength;h++) {
			for(int j=0,lineArraylength=lineArray.size();j<lineArraylength;j++) {
				lineArray1 =(JSONArray) lineArray.get(j);
				if(lineArraylist.get(h).equals(lineArray1.get(0))) {
					//线上条件判断
					String res = "";
					String decValue = "";
					res = lineArray1.get(5).toString();
					String[] reslist =  res.split("&@");
					for(int l=0,reslistlength=reslist.length;l<reslistlength;l++) {
						if(reslist[l].equals("1#")) {
							decValue += "&&";
						}else if(reslist[l].equals("2#")){
							decValue += "||";
						}else {
							if(reslist[l].contains("==")) {
								String[] reslist1 = reslist[l].replaceAll("#", "").split("==");
								Iterator<String> it2 = inputjson.keys(); 
								while(it2.hasNext()){
									// 获得key
									String key = it2.next(); 
									//特别注意数字不带单引号，字符串带单引号
									reslist1[1] = reslist1[1].replaceAll(key, NumericRegxUtils.isNumber(inputjson.getString(key))?inputjson.getString(key):"'"+inputjson.getString(key)+"'");
								}
								decValue = decValue + valString+"=="+reslist1[1];
							}else {
								Iterator<String> it3 = inputjson.keys(); 
								while(it3.hasNext()){
									// 获得key
									String key = it3.next(); 
									//特别注意数字不带单引号，字符串带单引号
									if (reslist[l].contains("@" + key + "@")) {
										if(extractStrings(reslist[l]).stream().filter(s -> s.split("\\.").length >= 2).collect(Collectors.toList()).size() > 0) {
											// @sqlVar2.NAME@.contains(@sqlVar2.NAME@)
											List<String> sqlVarList = extractStrings(valString).stream().filter(s -> s.split("\\.").length >= 2)
													.collect(Collectors.toList());
											for (String sqlVar : sqlVarList) {
												String[] sqlSplit = sqlVar.split("\\.");
												// 取出需要对比的字段
												String compareVar = sqlSplit[1];
												List<Object> columnValueList = new ArrayList<>();
												if (sqlSplit[0].equals(key)) {
													List<Map<String, Object>> listObjectFir = (List<Map<String, Object>>) com.alibaba.fastjson.JSONArray
															.parse((String) sqlCache.get(key));
													if (CollectionUtils.isEmpty(listObjectFir)) {
														try {
															listObjectFir = selectRuleSqlParamRes(inputjson, key, env);
														} catch (SQLException e) {
															e.printStackTrace();
														}
													}
													columnValueList = listObjectFir.stream()
															.filter(mapF -> Optional.ofNullable(mapF.get(compareVar)).isPresent()).map(mapV -> {
																Object value = mapV.get(compareVar);
																return value;
															}).collect(Collectors.toList());
													env.put(sqlVar.replaceAll("\\.", ""), columnValueList);
													valString = valString.replaceAll("\\@" + sqlVar + "\\@", sqlVar.replaceAll("\\.", ""));
													valStringOld = valStringOld.replaceAll("\\@" + sqlVar + "\\@", map.get(key).toString());
												} else {
													break;
												}
											}
										}else {
											// 根据参数名称查询SQL参数
											try {
												selectRuleSqlParamRes(inputjson, key, env);
											} catch (SQLException e) {
												e.printStackTrace();
											}
											reslist[l] = reslist[l].replaceAll("\\@", "");
										}
									}else {
										reslist[l] = reslist[l].replaceAll(key, NumericRegxUtils.isNumber(inputjson.getString(key))?inputjson.getString(key):"'"+inputjson.getString(key)+"'");
									}
								}
								
								if(reslist[l].contains("#")) {
									// 扩展多个操作符
									if (reslist[l].contains(OpTypeEnums.CONTAINS.getOperatePrefix())) {
										decValue = decValue + valString.replaceAll("\\'", "") + reslist[l].replaceAll("#", "");
									} else if(reslist[l].contains(OpTypeEnums.NOT_CONTAINS.getOperatePrefix())){
										decValue = decValue + "!" +valString.replaceAll("\\'", "") + reslist[l].replaceAll("notcontains", "contains").replaceAll("#", "");
									} else if(!reslist[l].contains("&&") && !reslist[l].contains("||")){
										decValue = decValue + valString + (reslist[l].replaceAll("#", ""));
									} else {
										decValue = decValue + (reslist[l].replaceAll("#", ""));
									}
								}else {
									decValue = decValue + valString+"=="+reslist[l].replaceAll("#", "");
								}
								
							}
						}
					}
					try {						
						Expression compile = AviatorEvaluator.compile(decValue,true);
						result = (Boolean)compile.execute(env);
						if(result) {
							if(resultArray1.get(2).equals("area")) {
								if(areaFirst.equals("")) {//判断是否是循环的第一个 节点
									areaFirst = resultArray1.getString(0);
									reJson.put("areaFirst", areaFirst);
								}
							}
							reason = reason.append("满足：").append(valStringOld).append(lineArray1.get(1).toString()).append(",");
							inputjson = getEveryNodeList(inputjson,lineArray1.get(0).toString(),resultArray1.get(2).toString(),resultArray1.get(0).toString(),ruleId,0,reason,map,startDate,inParam,null);
							reJson = recRun(lineArray1.get(4).toString(),inputjson,nodeArray,lineArray,areaArray,areaFirst,ruleId,reason,map);
							return reJson;
						}
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			}
		}
		// 结束执行时间
		Date endDate = DateUtils.getNowDate();
		String endExecuateTime = DateUtils.formatDate(endDate, DateUtils.YYYY_MM_DD_HH_MM_SS);
		reJson.put("startExecTime", startExecuateTime);
		reJson.put("endExecTime", endExecuateTime);
		reJson.put("execTotalTimeMills", "耗时: "+(endDate.getTime() - startDate.getTime())+" 毫秒");
		reJson.put("execStatus", RuleConstants.NODE_EXEC_SUCCESS);
		return reJson;
	}
	
	@Override
	public void onEvent(AppBeanLoadEndEvent event) throws Throwable {
		NodeExecFactory.register(NodeExecEnums.SWITCH_NODE.getCode(), this);
	}

}
